package jdk8feature.datetime;


import lombok.Data;
import lombok.ToString;

import java.io.Serializable;
import java.time.LocalDate;
import java.time.Period;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.List;

@ToString
public class BillCalculate {
    private Integer term;
    private LocalDate subscribeStartDate;
    private LocalDate subscribeEndDate;
    private LocalDate reviewStartDate;
    private LocalDate reviewEndDate;

    public BillCalculate(Integer term, String subscribeStartDate, String subscribeEndDate, String reviewStartDate, String reviewEndDate) {

        this.term = term;
        this.subscribeStartDate = LocalDate.parse(subscribeStartDate);
        this.subscribeEndDate = LocalDate.parse(subscribeEndDate);
        this.reviewStartDate = LocalDate.parse(reviewStartDate);
        this.reviewEndDate = LocalDate.parse(reviewEndDate);

        checkDate();
    }
    public static void main(String[] args) {

        test1(new BillCalculate(12, "2020-02-28", "2023-08-28"
                , "2020-02-28", "2023-08-28"));

        test1(new BillCalculate(3, "2020-02-28", "2021-02-27"
                , "2021-01-29", "2021-02-27"));


        test1(new BillCalculate(1, "2020-02-28", "2023-08-28"
                , "2021-05-01", "2023-08-28"));


        test1(new BillCalculate(12, "2023-02-01", "2025-01-31"
                , "2023-05-02", "2025-01-31"));
    }


    private void checkDate() {
        if (this.reviewStartDate.isBefore(this.subscribeStartDate))
            throw new IllegalArgumentException("date invalid.");
    }

    public List<BillPeriod> splitPeriod() {
        BillPeriod b1 = null, b2 = null, b3 = null;
        LocalDate subStart = this.subscribeStartDate;
        LocalDate subEnd = this.subscribeEndDate;
        LocalDate reviewStart = this.reviewStartDate;
        LocalDate reviewEnd = this.reviewEndDate;
        LocalDate freqNextStart = null;
        //subS,reviewS,firstCycleEnd,subE
        //第一个partial,用于changeQty，所以必须有partial
        long monthBetween = ChronoUnit.MONTHS.between(subStart, reviewStart);
        LocalDate firstEnd = currentFreqEnd(subStart, (int) (1 + (monthBetween / term)));
        b1 = buildBillPeroid(reviewStart, firstEnd);

        //后面的账单都应该是total qty
        freqNextStart = firstEnd.plusDays(1);
        Period period = Period.between(freqNextStart, subEnd.plusDays(1));
        if (!period.isNegative()) {
            int cnt;
            //中间的整周期，
            if ((cnt = (period.getYears() * 12 + period.getMonths()) / term) > 0) {
                b2 = buildBillPeroid(freqNextStart, currentFreqEnd(freqNextStart, cnt));
                freqNextStart = b2.getEndDate().plusDays(1);
            }
            //最后的partial
            if (freqNextStart.isBefore(subEnd)) {
                b3 = buildBillPeroid(freqNextStart, subEnd);
            }
        }

        return Arrays.asList(b1, b2, b3);

    }

    private LocalDate currentFreqEnd(LocalDate freqStart, Integer cycleCut) {
        return freqStart.plusMonths(cycleCut * term).minusDays(1);
    }

    private BillPeriod buildBillPeroid(LocalDate start, LocalDate end) {
        BillPeriod billPeroid = new BillPeriod();
        billPeroid.setBillDays((int) ChronoUnit.DAYS.between(start, end.plusDays(1)));
        billPeroid.setStartDate(start);
        billPeroid.setEndDate(end);
        billPeroid.setTerms(term);
        return billPeroid;
    }



    private static void test1(BillCalculate billCalculate) {
        System.out.println("----------------------------------------------------------");
        System.out.println(billCalculate.toString());
        List list = billCalculate.splitPeriod();
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        System.out.println("----------------------------------------------------------");
    }

}
